package edu.umn.contactviewer.task;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;

import android.net.http.AndroidHttpClient;
import android.os.AsyncTask;
import android.util.Log;

import com.google.gson.Gson;

import edu.umn.contactviewer.Contact;
import edu.umn.contactviewer.constant.ContactViewerConstants;
import edu.umn.contactviewer.datastore.ContactListDataService.RequestResult;
import edu.umn.contactviewer.datastore.UpdateContactRequestResponseListener;

public class UpdateContactAsyncTask extends
		AsyncTask<String, Void, Boolean> {

	private static final String TAG = "UpdateContact";
	private final Gson gson = new Gson();
	private static final String EMPTY = "";
	
	private Contact contactToUpdate;
	private UpdateContactRequestResponseListener responseListener;

	// for GSON serialization
	public static class UpdateContactResponse {

		public static class GroupCharateristics {
			private String key;
			private String name;
			private String _id;

			public String getKey() {
				return key;
			}

			public void setKey(String key) {
				this.key = key;
			}

			public String getName() {
				return name;
			}

			public void setName(String name) {
				this.name = name;
			}

			public String get_id() {
				return _id;
			}

			public void set_id(String _id) {
				this._id = _id;
			}
		}

		private String status;
		private String message;
		private GroupCharateristics group;
		private ArrayList<Contact> contacts;

		public String getStatus() {
			return status;
		}

		public void setStatus(String status) {
			this.status = status;
		}

		public String getMessage() {
			return message;
		}

		public void setMessage(String message) {
			this.message = message;
		}

		public GroupCharateristics getGroup() {
			return group;
		}

		public void setGroup(GroupCharateristics group) {
			this.group = group;
		}

		public List<Contact> getContacts() {
			return contacts;
		}

		public void setContacts(ArrayList<Contact> contacts) {
			this.contacts = contacts;
		}
	}
	
	public UpdateContactAsyncTask(Contact contactToUpdate, UpdateContactRequestResponseListener responseListener) {
		
		this.contactToUpdate = contactToUpdate;
		this.responseListener = responseListener;
	}

	@Override
	protected Boolean doInBackground(String... arg0) {
		
		// Initialize to error response in case of exceptions.
		Boolean result = false;
		
		try {
			AndroidHttpClient client = AndroidHttpClient.newInstance("Android",
					null);
			HttpUriRequest request = new HttpPut(
					ContactViewerConstants.WEB_SERVICE_URL
					+ ContactViewerConstants.SEPARATOR_SLASH
					+ contactToUpdate.get_id()
					+ ContactViewerConstants.SEPARATOR_QUERY_STRING
					+ ContactViewerConstants.API_KEY_MAPPING
					+ ContactViewerConstants.SEPARATOR_AND
					+ updateContactPutRequestContent(this.contactToUpdate)); // Enhance URI for put - contacts/<id>?key=greenzebras&name=...
			
			HttpResponse response = client.execute(request);
			InputStream in = response.getEntity().getContent();
			String jsonResponse = readJsonResponse(in);

			UpdateContactResponse updateContactResponse = gson.fromJson(
					jsonResponse, UpdateContactResponse.class);

			if (updateContactResponse.getStatus().equalsIgnoreCase("success")) {
				result = true;
			}

			client.close();

		} catch (IOException ex) {
			Log.e(TAG + "IO Exception: ", ex.toString());
		} catch (Exception ex) {
			Log.e(TAG + "Exception: ", ex.toString());
		}

		return result;
	}
	
	@Override
	protected void onPostExecute(Boolean result) {
		super.onPostExecute(result);
		
		RequestResult requestResult = RequestResult.FAIL;
		if (result) {
			requestResult = RequestResult.SUCCESS;
		}
		
		responseListener.onUpdateContactResponse(requestResult, this.contactToUpdate);
	}
	
	private String updateContactPutRequestContent(Contact contact) {
		StringBuilder contactPutRequestContentBuilder = new StringBuilder("");
		contactPutRequestContentBuilder.append("name=");
		contactPutRequestContentBuilder.append(getContactStringValue(contact.getName()));
		contactPutRequestContentBuilder.append(ContactViewerConstants.SEPARATOR_AND);
		contactPutRequestContentBuilder.append("title=");
		contactPutRequestContentBuilder.append(getContactStringValue(contact.getTitle()));
		contactPutRequestContentBuilder.append(ContactViewerConstants.SEPARATOR_AND);
		contactPutRequestContentBuilder.append("email=");
		contactPutRequestContentBuilder.append(getContactStringValue(contact.getEmail()));
		contactPutRequestContentBuilder.append(ContactViewerConstants.SEPARATOR_AND);
		contactPutRequestContentBuilder.append("phone=");
		contactPutRequestContentBuilder.append(getContactStringValue(contact.getPhone()));
		contactPutRequestContentBuilder.append(ContactViewerConstants.SEPARATOR_AND);
		contactPutRequestContentBuilder.append("twitterId=");
		contactPutRequestContentBuilder.append(getContactStringValue(contact.getTwitterId()));
		
		Log.e(UpdateContactAsyncTask.class.getSimpleName(),
			  "Update string: " + contactPutRequestContentBuilder.toString());
		
		return contactPutRequestContentBuilder.toString();
	}
	
	private String getContactStringValue(String contactString) {
		String value = EMPTY;
		try {
			value = URLEncoder.encode(null != contactString ? contactString : EMPTY, "utf-8");
		} catch (UnsupportedEncodingException e) {
			Log.e(TAG, "Stupid encoder...");
		}
		return value;
	}

	private String readJsonResponse(InputStream in) throws IOException {
		String jsonResponse = "";
		BufferedReader buffer = new BufferedReader(new InputStreamReader(in));
		String s = "";
		while ((s = buffer.readLine()) != null) {
			jsonResponse += s;
		}
		buffer.close();

		return jsonResponse;
	}
}
